<?php declare(strict_types=1);
/**
 * This file is part of Swoft.
 *
 * @link https://swoft.org
 * @document https://swoft.org/docs
 * @contact group@swoft.org
 * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE
 */

namespace App\Http\Middleware;

use App\Rpc\Lib\UserInterface;
use Firebase\JWT\JWT;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Swoft\Bean\Annotation\Mapping\Bean;
use Swoft\Http\Message\Request;
use Swoft\Http\Server\Contract\MiddlewareInterface;
use Swoft\Log\Helper\CLog;
use Swoft\Rpc\Client\Annotation\Mapping\Reference;
use function context;

/**
 * Class AuthorizeMiddleware - Custom middleware
 * @Bean()
 */
class AuthorizeMiddleware implements MiddlewareInterface
{
    /**
     * Process an incoming server request.
     *
     * @param ServerRequestInterface|Request  $request
     * @param RequestHandlerInterface $handler
     *
     * @return ResponseInterface
     * @inheritdoc
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $response = $handler->handle($request);
        $data = $response->getData();
        $iss = $request->getUri()->getHost();//签发者
        $aud = '*.'.root_domain($request);//接收者

        /**
         * 授权动作调用与用户服务的授权
         * 这里涉及到授权策略的选择，实际上关于“授权”这个逻辑的需求，在应用中可能存在多处调用
         * 所以关于逻辑的实现，其实可以抽象出来，建议放到逻辑类(logic)中，这样以后需求起来了代码能够更灵活
         */
//        $jwt = $this->userService->authorize(['id'=>$data['id']],$iss,$aud);
        $jwt = $this->authorize(['id'=>$data['id']],$iss,$aud);
        return $response
            ->withHeader('Access-Control-Expose-Headers','Authorization')
            ->withHeader('Authorization',"Bearer $jwt");

        // after request handle
    }

    /**
     * 颁发授权
     * @param array $data
     * @param string $iss
     * @param string $aud
     * @return string
     */
    public function authorize(array $data,string $iss,string $aud): string
    {
        $time = time();
        $token = [
            'iat' => $time,//签发时间
            'nbf' => $time,//生效时间，比如设置time+30，表示当前时间30秒后才能使用
            'exp' => $time + 3600*24*30,//过期时间30天，前后台一致
            "iss" => $iss,//签发者  ex: swoft.duzhaoteng.com
            'aud' => $aud,//接收者  ex: *.duzhaoteng.com
            'data' => $data,
//            'data' => [//自定义信息，不要存储敏感信息
//                'id' => $data['id'],//例如用户主键id
//                'mobile' => $data['mobile'],//用户手机号
//                //等等...
//            ],
        ];

        return JWT::encode($token, config('secret.jwt', 'CT5'),'HS256');
    }
}
